home *** CD-ROM | disk | FTP | other *** search
- ; Subroutine.: DISKSTAT.ASM
- ; Author.....: Kelly Mc Tiernan
- ; Date.......: 1983
- ; Notice.....: Copyright 1983, Kelly Mc Tiernan, All Rights Reserved
- ; Notes......: CP/M-80 disk drive status routine.
- ;
- BDOS EQU 00005H
- FDPB EQU 1FH
- FALV EQU 1BH
- FDSK EQU 19H
- FCHG EQU 0EH
- ;
- ORG 42000
- ;
- START: SHLD SAVEHL ; SAVE HL REG PAIR
- MVI C,FDSK ; DETERMINE CURRENT DISK
- PUSH H ; SAVE HL
- CALL BDOS ;
- STA SAVDSK ; AND SAVE TO RESTORE
- POP H ; GET IT BACK
- INX H ; POINT TO FIRST BYTE OF VARIABLE
- MOV A,M ; GET IT
- ORA A ; CLEAR CARRY
- SBI 41H ; CONVERT ASCII A,B,C TO 0,1,2,..
- CPI 10H ; LEGAL DRIVE NAME?
- JNC KEEPDR ; NO, KEEP CURRENT DRIVE
- MOV E,A ; GET DRIVE TO SELECT
- MVI C,FCHG ; SELECT FUNCTION
- CALL BDOS ;
- ;
- KEEPDR: LXI H,0000H ; TO SAVE SP
- DAD SP ; GET SP
- SHLD SAVESP ; SAVE IT
- MVI A,01H ; TO INIT. SIG. DIGIT POINTER
- LXI H,ANSWER ; WHERE IT GOES
- MOV M,A ; INITIALIZE
- MVI C,FDPB ; GET DPB ADDRESS
- CALL BDOS ; HL HAS ADDRESS
- SHLD DPBADR ; SAVE BASE ADDRESS
- LXI B,0005H ; OFFSET TO DSM
- DAD B ;
- MOV E,M ; GET FIRST BYTE
- INX H ; FOR NEXT BYTE
- MOV D,M ; GET IT
- XCHG ; GET WHERE IT CAN BE USED
- MVI B,03H ; COUNT FOR SHIFT
- DIV8: ORA A ; CLEAR CARRY FOR DIVISION
- MOV A,H ; GET FIRST BYTE
- RAR ; DIVIDE BY 2
- MOV H,A ; RESTORE HIGH BYTE
- MOV A,L ; GET LOW BYTE
- RAR ; DIVIDE BY 2 (SHIFT IN HB CARRY)
- MOV L,A ; RESTORE IT
- DCR B ; FOR COUNT
- JNZ DIV8 ; CONTINUE 3 TIMES (2*2*2=8)è INX H ; +1=ALV LENGTH
- SHLD ALVLNG ; SAVE LENGTH OF ALV
- ;
- ; NOW CALCULATE BLOCK SIZE FOR DRIVE
- ;
- LHLD DPBADR ; GET BACK BLOCK ADDRESS
- INX H ; VECTOR INTO DPB FOR BSH
- INX H ;
- MOV E,M ; GET IT
- MVI D,00H ; ZERO HB
- DCX D ; FOR VECTOR INTO TABLE
- DCX D ;
- DCX D ;
- MOV A,E ; GET IT
- ORA A ; CLEAR CARRY
- RAL ; MULTIPLY BY 2
- MOV E,A ; GET BACK VECTOR
- LXI H,TABLE ; BASE ADDRESS
- DAD D ; ADD IN VECTOR
- MOV E,M ; GET LB (STORED LB,HB)
- INX H ; NEXT BYTE
- MOV D,M ; DE NOW CONTAINS BLOCK SIZE
- XCHG ; GET IT TO WHERE WE CAN SAVE IT
- SHLD BLS ; SAVE IT
- ;
- ;
- ; NOW LET'S DETERMINE SPACE LEFT ON DISK
- ;
- MVI C,FALV ; LET'S GET ALV ADDRESS NOW
- CALL BDOS ; HL CONTAINS ADDRESS
- LDA ALVLNG ; GET LENGTH
- MOV B,A ; INTO COUNTER 1
- LXI D,0000H ; BIT COUNTER ZEROED
- DCX H ; SET FOR LOOP CONTROL
- SHLD TEMP ; SAVE HL
- DI ; DISABLE INTERRUPTS BEFORE SP
- ; CHANGE
- LHLD BLS ; GET BLOCK SIZE
- SPHL ; FOR ADDITION
- LXI H,0000H ; INITIALIZE
- SHLD SIZE0 ; " "
- SHLD SIZE1 ; " "
- BITCNT: LHLD TEMP ; RESTORE HL
- INX H ; POINT TO BYTE
- MVI C,08H ; COUNTER 2 FOR BITS/BYTE
- MOV A,M ; GET FIRST BYTE
- ORA A ; CLEAR CARRY
- SHLD TEMP ; SAVE HL POINTER
- BIT1: LHLD SIZE0 ; GET LOW WORD TOTAL
- RAR ; ROTATE A TO COUNT ZERO BITS
- JC BIT2 ; DON'T COUNT 1'S
- DAD SP ; IF UNALLOC. THEN ADD 1 BLOCK
- ; TO TTL.
- JNC BIT2 ; IF NO CARRY FROM DAD H
- INX D ; ELSE ADD 1 TO HIGH WORDèBIT2: SHLD SIZE0 ; SAVE NEW LOW WORD FOR UNALLOC.
- DCR C ; COUNTER
- JNZ BIT1 ; NEXT BIT
- DCR B ; COUNT FOR BYTES
- JNZ BITCNT ; DO NEXT BYTE
- XCHG ; GET HIGH WORD INTO HL
- SHLD SIZE1 ; SAVE IT
- LHLD SIZE0 ; FOR CORRECTION FACTOR
- LXI SP,0E000H ; ERROR OFFSET
- DAD SP ; TWO'S COMP. OF 2000H (SUBTRACT
- ; OFFSET)
- SHLD SIZE0 ; SAVE RESULT
- JC EX1 ; EXIT IF CARRY (LOW WORD >
- ; 2000H)
- LHLD SIZE1 ; FOR BORROW
- DCX H ; SUBTRACT 1
- SHLD SIZE1 ; SAVE RESULT
- EX1: LHLD SAVESP ; RESTORE STACK POINTER
- SPHL ;
- EI ; ENABLE INTERRUPTS
- ;
- ;
- ; NOW WE CONVERT TO A DECIMAL STRING
- ;
- LXI H,ANSWER+1 ; TO INITIAIZE DATA AREA
- MVI B,0AH ; COUNTER
- MVI A,00H ; INITIALIZE TO 0
- INIT1: MOV M,A ;
- INX H ; NEXT BYTE
- DCR B ;
- JNZ INIT1 ; REPEAT FOR 10 BYTES
- MVI C,0AH ; TOTAL # OF SIG DIGITS COUNTER
- LXI H,SIZE0 ; POINTER TO LOWEST BYTE
- XCHG ; SAVE IT
- LXI H,TBL2 ; POINT TO SUBTRACTION TABLE
- XCHG ; GET BACK DATA TABLE ADDRESS
- MINUS: ORA A ; CLEAR CARRY FOR LOW BYTE
- MVI B,03H ; COUNTER FOR SUBS
- MIN0: MOV A,M ; GET DATA
- XCHG ; GET SUB TABLE POINTER
- SBB M ; SUBTRACT DIGIT
- INX H ; POINT TO NEXT TABLE ENTRY
- XCHG ; GET BACK DATA POINTER
- MOV M,A ; PUT BACK RESULT
- INX H ; POINT TO NEXT DATA BYTE
- DCR B ; DONE WITH LOW 3 BYTES ?
- JNZ MIN0 ; CHECK FOR NEG ON LAST BYTE SBB
- LAST1: MOV A,M ; GET MOST SIG BYTE
- XCHG ; GET TABLE POINTER
- SBB M ; SUBTRACT IT
- DI ; DISABLE INTERUPTS BEFORE CALL
- CP AD1 ; ADD 1 TO SIG DIGIT IF IT WENT
- EI ; ENABLE INTERUPTS ON RETURN
- DCX H ; MOVE POINTER BACK TO BEGINNING
- DCX H ; OF TABLEè DCX H ;
- XCHG ; GET BACK DATA POINTER
- MOV M,A ; PUT BACK RESULT
- DCX H ; MOVE POINTER BACK TO BEGINNING
- DCX H ; OF DATA
- DCX H ;
- DI ; DISABLE INTERUPTS
- CM PUTBK ; PUT BACK IF NEG AND MOVE ON
- EI ; ENABLE INTERUPTS
- DCR C ; ONLY TO OVERRIDE SBB M
- INR C ;
- JNZ MINUS ; NO, DO AGAIN
- ;
- ;
- ; NOW LETS CONVERT TO ASCII (ADD 30H) AND PASS BACK
- ; TO 10 DIGIT DBASE VARIABLE
- ;
- LXI H,ANSWER+1 ; POINT TO ANSWER BUFFER
- MVI B,0AH ; FOR ALL 10 BYTES
- FILL: MVI A,30H ; TO CONVERT TO ASCII
- ADD M ; UNPACKED BCD+30=ASCII
- MOV M,A ; PUT CORRECTED ANSWER BACK
- INX H ; NEXT DIGIT
- DCR B ; DONE ?
- JNZ FILL ;
- LHLD SAVEHL ; OLD HL POINTER (VERY OLD)
- MOV A,M ; LET'S DO A LITTLE ERROR
- ; CHECKING
- CPI 0AH ;
- JNZ ERROR ; VARIABLE WRONG LENGTH
- INX H ; NOW LET'S GIVE dBASE THE ANSWER
- XCHG ; I KINDA LIKE THIS INSTRUCTION
- LXI H,ANSWER+1 ; SHOULD BE OBVIOUS BY NOW
- MVI B,0AH ; COUNTER TO MOVE BYTES
- PASS: MOV A,M ; GET BYTE
- INX H ; FOR NEXT BYTE
- XCHG ; WHERE TO SEND
- MOV M,A ; SEND IT
- INX H ; WHERE TO SEND NEXT ONE
- XCHG ; BACK TO SOURCE POINTER
- DCR B ; COUNTER FOR BYTES PASSED
- JNZ PASS ; DO NEXT BYTE
- JMP FINIS ; NORMAL END OF ROUTINE
- ERROR: INX H ; POINT TO FIRST BYTE
- MVI A,'E' ; ERROR CODE
- MOV M,A ; SEND ERROR CODE TO DBASE
- FINIS: LDA SAVDSK ; GET BACK DISK IN USE NO.
- MOV E,A ; PUT IN E FOR BDOS CALL
- MVI C,FCHG ; FUNCTION TO CHANGE DISK
- CALL BDOS ; BACK TO ORIGINAL DRIVE
- LHLD SAVESP ; RESTORE SP
- SPHL ;
- LHLD SAVEHL ; RESTORE HL
- RET
- ;è;
- ; SUBROUTINES FOR CALCULATIONS
- ;
- PUTBK: ORA A ; CLEAR CARRY
- MVI B,04H ; COUNTER FOR ADDS
- PUT1: MOV A,M ; GET DATA
- XCHG ; POINT TO SUB TABLE
- ADC M ; ADD BACK IN AMMOUNT
- INX H ; POINT TO NEXT SUB TABLE BYTE
- XCHG ; BACK TO DATA POINTER
- MOV M,A ; PUT BACK RESULT
- INX H ; POINT TO NEXT DATA BYTE
- DCR B
- JNZ PUT1 ; NEXT BYTE
- DCX H ; RESET DATA POINTER
- DCX H ;
- DCX H ;
- DCX H ;
- PUSH H ; SAVE HL
- LXI H,ANSWER ; POINT TO SIG DIGIT POINTER
- INR M ; INCREMENT TO NEXT DIGIT
- POP H ; RESTORE HL
- DCR C ; COUNT FOR SIG DIGITS DONE
- RET ; RETURN TO CALLER
- ;
- AD1: PUSH PSW ; SAVE REGISTERS
- PUSH B ;
- PUSH D ;
- PUSH H ;
- LXI H,ANSWER ; ANSWER TABLE
- MOV E,M ; GET POSITION
- MVI D,00H ; FOR VECTOR
- DAD D ; VECTOR TO SIG DIGIT
- INR M ; ADD 1 TO DIGIT
- POP H ; RESTORE REGISTERS
- POP D ;
- POP B ;
- POP PSW ;
- RET ;
- ;
- SAVEHL: DS 2
- SAVESP: DS 2
- DPBADR: DS 2
- ALVLNG: DS 2
- BLS: DS 2
- TEMP: DS 2
- SAVDSK: DS 1
- ;
- TABLE: DB 00H
- DB 04H
- DB 00H
- DB 08H
- DB 00H
- DB 10H
- DB 00Hè DB 20H
- DB 00H
- DB 40H
- ;
- SIZE0: DS 2
- SIZE1: DS 2
- ;
- ;
- ANSWER: DS 10H ; TOTAL SIG DIGITS+POINTER
- ;
- TBL2: DB 000H,0CAH,09AH,03BH
- DB 000H,0E1H,0F5H,005H
- DB 080H,096H,098H,000H
- DB 040H,042H,00FH,000H
- DB 0A0H,086H,001H,000H
- DB 010H,027H,000H,000H
- DB 0E8H,003H,000H,000H
- DB 064H,000H,000H,000H
- DB 00AH,000H,000H,000H
- DB 001H,000H,000H,000H
- ;
- END